package com.yoyo.itravel.service.impl;

import com.yoyo.itravel.bean.PageBean;
import com.yoyo.itravel.bean.Permission;
import com.yoyo.itravel.bean.Role;
import com.yoyo.itravel.bean.User;
import com.yoyo.itravel.dao.IPermissionDao;
import com.yoyo.itravel.dao.IRoleDao;
import com.yoyo.itravel.dao.IUserDao;
import com.yoyo.itravel.exceptions.UserException;
import com.yoyo.itravel.service.IUserService;
import com.yoyo.itravel.utils.MD5Utils;
import com.yoyo.itravel.utils.StringUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;

/**
 * @Description 用户操作服务层接口实现类
 * @Author HZX
 * @Version 1.0
 * @Date 2020/6/20 11:32
 */
@Service
public class UserServiceImpl implements IUserService {
    // 实例化用户持久层接口对象
    @Autowired
    private IUserDao userDao;
    // 实例化角色持久层接口对象
    @Autowired
    private IRoleDao roleDao;
    // 实例化角色持久层接口对象
    @Autowired
    private IPermissionDao permissionDao;

    /**
     * @Description 用户注册
     *
     * @Param user
     * @Return boolean
     */
    @Override
    public boolean register(User user) throws UserException {
        // 判断user是否为null
        if (user == null) {
            // user为null，抛出异常
            throw new UserException("传入的user对象为空...");
        }
        try {
            String phone = null;
            String email = null;
            // 判断用户是手机注册还是邮箱注册
            if ((phone = user.getPhone()) != null) { // 手机注册
                // 判断该手机号是否已被注册
                isPhoneAlreadyExist(phone);
            } else if ((email = user.getEmail()) != null) { // 邮箱注册
                // 判断该邮箱是否已被注册
                isEmailAlreadyExist(email);
            }

            /* 补充用户对象中的信息 */
            // 对密码进行加密
            user.setPassword(MD5Utils.md5(user.getPassword()));
            // 设置用户id
            user.setUserId(StringUtils.getRandomUUID());
            // 获得当前时间
            Date nowDateTime = new Date();
            // 设置用户注册时间
            user.setRegisterTime(nowDateTime);
            // 设置用户信息修改时间(此时，修改时间为注册时间)
            user.setUpdateTime(nowDateTime);

            // 添加用户
            userDao.addUser(user);
            // 注册成功，返回true
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("添加用户失败...");
        }
    }

    /**
     * @Description 用户登录（手机号或邮箱登录）
     *
     * @Param phone_email
     * @Param password
     * @Return com.yoyo.itravel.bean.User
     */
    @Override
    public User login(String phone_email, String password) throws UserException {
        /* 不知道为什么有的时候没有注入成功，导致空指针异常，所以加个判断 */
        if (userDao == null) {
            return null;
        }
        // 非空判断
        if (StringUtils.isEmpty(phone_email, password)) {
            return null;
        }

        User user = null;

        try {
            // 判断是邮箱还是手机登录
            if (StringUtils.isDigital(phone_email)) { // 为纯数字，可能为手机号
                // 通过手机号查询用户
                if (userDao.selectByPhone(phone_email) == null) {
                    throw new UserException("账号不存在，请先注册账号！");
                }
                // 账号存在，通过手机号和密码查询用户
                user = userDao.selectByPhoneAndPassword(phone_email, password);
            } else { // 可能为邮箱
                // 通过邮箱号查询用户
                if (userDao.selectByEmail(phone_email) == null) {
                    throw new UserException("账号不存在，请先注册账号！");
                }
                // 通过邮箱号和密码查询用户
                user = userDao.selectByEmailAndPassword(phone_email, password);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("通过手机号或邮箱查找用户失败...");
        }
        // 判断是否查询到用户
        if (user == null) {
            throw new UserException("账号或密码输入错误！");
        }

        // 判断用户账号的状态是否正常
        if (user.getStatus() != 1) {
            throw new UserException("您的账号不可用，请联系管理员！");
        }

        // 判断用户是否已经登录
        // if (user.getOnlineStatus() == 1) {
        //     throw new UserException("您已登录账号！");
        // }

        return user;
    }

    /**
     * @Description 管理员登录
     *
     * @Param phone_email
     * @Param password
     * @Return com.yoyo.itravel.bean.User
     */
    @Override
    public User adminLogin(String phone_email, String password) throws UserException {
        // 非空判断
        if (StringUtils.isEmpty(phone_email, password)) {
            return null;
        }

        User user = null;

        try {
            // 判断是邮箱还是手机登录
            if (StringUtils.isDigital(phone_email)) { // 为纯数字，可能为手机号
                // 通过手机号查询用户
                if (userDao.selectByPhone(phone_email) == null) {
                    throw new UserException("账号不存在，请先注册账号！");
                }
                // 账号存在，通过手机号和密码查询用户
                user = userDao.selectByPhoneAndPassword(phone_email, password);
            } else { // 可能为邮箱
                // 通过邮箱号查询用户
                if (userDao.selectByEmail(phone_email) == null) {
                    throw new UserException("账号不存在，请先注册账号！");
                }
                // 通过邮箱号和密码查询用户
                user = userDao.selectByEmailAndPassword(phone_email, password);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("通过手机号或邮箱查找用户失败...");
        }
        // 判断是否查询到用户
        if (user == null) {
            throw new UserException("账号或密码输入错误！");
        }

        // 判断用户账号的状态
        if (user.getStatus() != 1) {
            throw new UserException("您的账号不可用，请联系管理员！");
        }

        try {
            // 获取用户的权限
            List<Permission> permissions = permissionDao.selectByUserId(user.getUserId());

            if (permissions == null || permissions.size() == 0) {
                // 如果查出来的权限集合为null，则表示当前用户没有权限登录后台系统
                throw new UserException("您没有权限登录，请先获得权限！");
            }

            for (Permission permission : permissions) {
                if (permission.getParentPermissionId() == null) {
                    // 表明该权限为一级权限
                    // 通过权限id查找它的子权限 -- 注意：目前只实现两级权限
                    List<Permission> childPermissions = permissionDao.selectByParentPermissionId(permission.getPermissionId());

                    if (childPermissions != null) {
                        permission.setChildPermissions(childPermissions);
                    }
                } else { // 子权限

                }
            }
            // 查找该用户的角色
            List<Role> roles = roleDao.selectAllByUserId(user.getUserId());
            user.setRoles(roles);
            user.setPermissions(permissions);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return user;
    }

    /**
     * @Description 注销账号
     *
     * @Param userId
     * @Return boolean
     */
    @Override
    public boolean deleteUser(String userId) throws UserException {
        if (StringUtils.isEmpty(userId)) {
            throw new UserException("用户id为空！");
        }
        try {
            return userDao.deleteByUserId(userId) == 1;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("通过用户id注销账号失败！");
        }
    }

    /**
     * @Description 通过用户id修改密码
     *
     * @Param id
     * @Param newPassword
     * @Return boolean
     */
    @Override
    public boolean updatePasswordById(String id, String newPassword) throws UserException {
        if (StringUtils.isEmpty(id, newPassword)) {
            throw new UserException("用户id或新密码为空！");
        }
        try {
            return userDao.updatePasswordById(id, newPassword) == 1;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("通过用户id修改密码失败！");
        }
    }

    /**
     * @Description 通过用户id查找用户
     *
     * @Param id
     * @Return com.yoyo.itravel.bean.User
     */
    @Override
    public User findById(String id) throws UserException {
        try {
            // 通过用户id查找用户
            return userDao.selectByUserId(id);
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("通过用户id查找用户失败！");
        }
    }

    /**
     * @Description 通过手机号查询用户
     *
     * @Param phone
     * @Return boolean
     */
    @Override
    public boolean isPhoneAlreadyExist(String phone) throws UserException {
        // 非空判断
        if (StringUtils.isEmpty(phone)) {
            throw new UserException("手机号不能为空！");
        }

        try {
            // 判断该手机号是否已被注册
            if (userDao.selectByPhone(phone) != null) {
                throw new UserException("该手机号已被注册，请直接登录！");
            }

            return false;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("通过手机号查询用户失败...");
        }
    }

    /**
     * @Description 通过邮箱查询用户
     *
     * @Param email
     * @Return boolean
     */
    @Override
    public boolean isEmailAlreadyExist(String email) throws UserException {
        // 非空判断
        if (StringUtils.isEmpty(email)) {
            throw new UserException("邮箱不能为空！");
        }

        try {
            // 判断该邮箱是否已被注册
            if (userDao.selectByEmail(email) != null) {
                throw new UserException("该邮箱已被注册，请直接登录！");
            }

            return false;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("通过邮箱查询用户失败...");
        }
    }

    /**
     * @Description 通过用户id修改用户头像
     *
     * @Param userId
     * @Param head_pic_src
     * @Return boolean
     */
    @Override
    public boolean changeHeadPic(String userId, String head_pic_src) throws UserException {
        try {
            return userDao.changeHeadPic(userId, head_pic_src) == 1;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("通过用户id修改用户头像失败...");
        }
    }

    /**
     * @Description 通过用户id修改用户个性签名
     *
     * @Param userId
     * @Param signatureVal
     * @Return boolean
     */
    @Override
    public boolean changeSignature(String userId, String signatureVal) throws UserException {
        try {
            return userDao.changeSignature(userId, signatureVal) == 1;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("通过用户id修改用户个性签名失败...");
        }
    }

    /**
     * @Description 通过修改用户id用户个人信息
     *
     * @Param userId
     * @Param user
     * @Return boolean
     */
    @Override
    public boolean updateUserInfo(String userId, User user) throws UserException {
        try {
            return userDao.updateUserInfo(userId, user) > 0;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("通过用户id修改用户个性签名失败...");
        }
    }

    /**
     * @Description 通过用户id修改用户邮箱
     *
     * @Param userId
     * @Param email
     * @Return boolean
     */
    @Override
    public boolean updateEmail(String userId, String email) throws UserException {
        try {
            return userDao.updateEmail(userId, email) == 1;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("通过用户id修改用户邮箱失败...");
        }
    }

    /**
     * @Description 通过用户id修改用户手机号
     *
     * @Param userId
     * @Param email
     * @Return boolean
     */
    @Override
    public boolean updatePhone(String userId, String email) throws UserException {
        try {
            return userDao.updateEmail(userId, email) == 1;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("通过用户id修改用户手机号失败...");
        }
    }

    /**
     * @Description 找回密码
     *
     * @Param phone_or_email
     * @Param new_pwd
     * @Return boolean
     */
    @Override
    public boolean retrievePwd(String phone_or_email, String new_pwd) throws UserException {
        // 声明User对象
        User user = null;
        try {
            // 判断账号是手机号还是邮箱
            if (StringUtils.isDigital(phone_or_email)) { // 手机号
                // 判断该手机号注册用户是否存在
                if ((user = userDao.selectByPhone(phone_or_email)) == null) {
                    throw new UserException("您还没有注册，请直接注册！");
                }

                // 判断是否使用了旧密码
                if (user.getPassword().equals(new_pwd)) {
                    throw new UserException("您使用了旧密码，请直接登录！");
                }

                // 更改密码
                userDao.updatePwdByPhone(phone_or_email, new_pwd);

            } else { // 邮箱
                // 判断该手机号注册用户是否存在
                if ((user = userDao.selectByEmail(phone_or_email)) == null) {
                    throw new UserException("您还没有注册，请直接注册！");
                }

                // 判断是否使用了旧密码
                if (user.getPassword().equals(new_pwd)) {
                    throw new UserException("您使用了旧密码，请直接登录！");
                }

                // 更改密码
                userDao.updatePwdByEmail(phone_or_email, new_pwd);
            }

            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("通过手机号或邮箱查找用户失败！");
        }
    }

    /**
     * @Description 修改用户的在线状态
     *
     * @Param userId
     * @Param onlineStatus
     * @Return boolean
     */
    @Override
    public boolean updateOnlineStatus(String userId, Integer onlineStatus) throws UserException {

        if (onlineStatus.intValue() != 1 && onlineStatus.intValue() != 0) {
            throw new UserException("参数有误！");
        }
        try {
            return userDao.updateOnlineStatus(userId, onlineStatus) == 1;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new UserException("修改用户的在线状态失败！");
        }
    }

    /**
     * @Description 分页查询所有用户
     *
     * @Param currentPage
     * @Param pageSize
     * @Return com.yoyo.itravel.bean.PageBean<com.yoyo.itravel.bean.User>
     */
    @Override
    public PageBean<User> findAllByPage(int currentPage, int pageSize) throws UserException {
        //封装PageBean
        PageBean<User> pb = new PageBean<User>();
        //设置当前页码
        pb.setCurrentPage(currentPage);
        //设置每页显示条数
        pb.setPageSize(pageSize);

        //设置当前页显示的数据集合
        int start = (currentPage - 1) * pageSize; // 开始的记录数
        pb.setStartPage(start);
        // 根据选择的条件获得的景点集合
        List<User> users = null;
        // 定义一个变量，表示总条数
        int totalCount = 0;

        try {
            // 查询的数据的总条数
            totalCount = userDao.selectTotalCount();

            // 设置总条数
            pb.setTotalCount(totalCount);
            // 获得所有用户
            users = userDao.selectAllByPage(start, pageSize);

            // TODO 排除当前登录的管理员
        } catch (SQLException e) {
            e.printStackTrace();
        }

        pb.setList(users);

        //设置总页数 = 总记录数/每页显示条数
        int totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : (totalCount / pageSize) + 1;
        pb.setTotalPage(totalPage);

        return pb;
    }
}
